#include<ModV550.hh>
#include<ModV551.hh>

#include <hbook.hh>

#include<stdio.h>
#include<signal.h>
#include<math.h>
#include<sys/time.h>

#define NumOfChan 1280
#define NumOfSil 3
#define BuffSize NumOfChan*NumOfSil

//VME ADC Modules V550
#define NumOfADC 2
ModV550* v550[NumOfADC];
bool ADC_Status[4];

#define Base_address_550 0x00860000
#define Step_address_550 0x000A0000

//VME Sequencer V551B
#define Base_address_551 0x00880000
ModV551* v551 = new ModV551(Base_address_551);

//signal
static int sig_int = 1;
static int sig_hup = 1;
void ctrl_c(int);
void hungup(int);

//FLAGS

static int FLAG_DAQ = 1;
static int FLAG_CALIB = 0;

char CharTmp[20];

//Function declarations
void DAQMenu();
int Run(int);
int RunDisplay(int);
void CalibExtTrig();
void CalibAutoTrig();
void SetZero();

int main(){
 
  /*---------------- VME modules initialisation ----------------*/

  /*** VME Sequencer V551B ***/
  v551->Init(NumOfChan);
  //v551->GetStatus();
  //v551->GetTest();
  
  /*** VME ADC Modules V550 ***/
  for(int i = 0; i < NumOfADC; i++){
    
    v550[i] = new ModV550(Base_address_550 + i*Step_address_550);
    v550[i]->Init(NumOfChan);
    //v550[i]->GetStatus();
    
  }//i
  
  //only 3 sillicon detectors
  ADC_Status[0] = true; //telescope module 1
  ADC_Status[1] = true; //telescope module 2
  ADC_Status[2] = false; //not active ADC in v550
  ADC_Status[3] = true; //telescope module 3

  /*---------------- VME modules initialisation ----------------*/

  /*----------------      signal handling      ----------------*/

  signal(SIGINT,ctrl_c);
  signal(SIGHUP,hungup);

  /*----------------      signal handling      ----------------*/

  /*----------------         DAQ menu          ----------------*/

  DAQMenu();

  /*----------------         DAQ menu          ----------------*/
  
  delete v551; 
  for(int i = 0; i < NumOfADC; i++) delete v550[i];
  
}//main program

/*----------------      signal handling      ----------------*/

void ctrl_c(int){
  sig_int = 0;
  printf("\n CTRL-C pressed \n\r"); 
}//ctrl_c

void hungup(int)
{
  sig_hup = 0;
  printf("\n Signal HUP received \n\r");
}//hungup

/*----------------      signal handling      ----------------*/

void DAQMenu(){

  while(FLAG_DAQ && sig_hup){
    
    printf("========================================== \n\r");
    printf("=                                        = \n\r");
    printf("=    DAQ for silicon MVD telescope       = \n\r");
    printf("=                                        = \n\r");
    printf("========================================== \n\r");
    printf(" R - Start Run                             \n\r");
    printf(" D - Start Run in the display mode         \n\r");
    printf(" A - Calibration with the auto trigger     \n\r");
    printf(" E - Calibration with the external trigger \n\r");
    printf(" Z - Set pedestals and thresholds to 0     \n\r");
    printf(" Q - Quit                                  \n\r");
    printf(" > ");
    
    fgets(CharTmp,20,stdin);
    CharTmp[0] = toupper(CharTmp[0]);

    switch(CharTmp[0]){
      
    case 'R':
      sig_int = 1;
      if(!FLAG_CALIB){
	printf("=========================================================================== \n\n\r");
	printf("!!! Warning: Before taking data you have to make calibration                  \n\r");
	printf("!!! Warning: Close the shutter and use calibration in the auto trigger mode   \n\n\r");
	printf("=========================================================================== \n\n\r");
	break;
      }
      printf("DAQ: Set the run number: ");
      fgets(CharTmp,20,stdin);
      Run(atoi(CharTmp));
      break;

    case 'D':
      sig_int = 1;
      if(!FLAG_CALIB){
	printf("=========================================================================== \n\n\r");
	printf("!!! Warning: Before taking data you have to make calibration                  \n\r");
	printf("!!! Warning: Close the shutter and use calibration in the auto trigger mode   \n\n\r");
	printf("=========================================================================== \n\n\r");
	break;
      }
      printf("DAQ: Set the run number: ");
      fgets(CharTmp,20,stdin);
      RunDisplay(atoi(CharTmp));
      break;

    case 'A':      
      CalibAutoTrig();
      break;

    case 'E':  
      CalibExtTrig();
      break;
    
    case 'Z':  
      SetZero();
      break;
  
    case 'Q':
      FLAG_DAQ = 0;
      break;
      
    default: 
      break;    

    }//switch
    
  }//while

}//RunMenu

int Run(int RunNumber){

  v551->Init(NumOfChan);
  for(int i = 0; i < NumOfADC; i++) v550[i]->Init(NumOfChan);

  char OFName[200];
  sprintf(OFName,"./DATA/si_run%d.dat",RunNumber);

  FILE* fp = fopen(OFName,"r");

  if(fp){

    printf("Do you want to rewrite file %s (y/n) \n\r",OFName);

    fgets(CharTmp,20,stdin);
    CharTmp[0] = toupper(CharTmp[0]);

    switch(CharTmp[0]){
      
    case 'Y':
      fclose(fp);
      fp = fopen(OFName,"w");
      break;
      
    case 'N':
      return 1;
      
    default:
      break; 
  
    }//switch
    
  }//if
  else{
    fp = fopen(OFName,"w");
    if(fp == NULL){
      printf("!!! Warning: Can not open file %s \n",OFName);
      return 1;
    }
  }

  /*---  Run note  ---*/
  printf("Note:");  
  fgets(OFName,200,stdin);
 
  unsigned int HitNumberADC0;
  unsigned int HitNumberADC1;

  unsigned int EVENT[BuffSize + 8];
  unsigned int ievent = 0;
  int iev;

  //event time 
  struct timeval tv;
  unsigned int sec;
  unsigned int microsec;
  time_t    timer;
  struct tm *date;

 /*---  write header  ---*/

  time(&timer);
  date = localtime(&timer);
  fprintf(fp,"*FORM = 04 marker=0xAABBCCDD\n");
  fprintf(fp,"*RUN = %d time %d:%d, date %d/%d/%d \n",RunNumber,date->tm_hour,date->tm_min,date->tm_mday,date->tm_mon+1,date->tm_year+1900);
  fprintf(fp,"*Calibration = %d, ",FLAG_CALIB);
  for(int im = 0; im < NumOfADC; im++){
    for(int ic = 0; ic < 2; ic++){ 
      fprintf(fp,"ADC %d = %d, ",ic + im*NumOfADC,ADC_Status[ic + im*NumOfADC]);
    }
  }
  fprintf(fp,"\n");
  
  fprintf(fp,"*init_SEQ: t1=%d, t2=%d, t3=%d, t4=%d, t5=%d \n",v551->time1,v551->time1,v551->time3,v551->time4,v551->time5);
  fprintf(fp,"*REM = %s",OFName);

  //taking data
  while(sig_int){
    
    while(!v551->GetBusy()) if(!sig_int) break;

    iev = 0;
    gettimeofday(&tv,NULL);
    sec = tv.tv_sec;
    microsec = tv.tv_usec;
    EVENT[iev++] = ievent;
    EVENT[iev++] = sec;
    EVENT[iev++] = microsec;
    EVENT[iev++] = 0;

    //waiting for data ready 
    while(!v551->GetDataRedy()) if(!sig_int) break;

    ievent++;
    
    //printf("Event = %d \n\r",ievent);

    for(int i = 0; i < NumOfADC; i++){
      
      v550[i]->GetWordCounter(HitNumberADC0,HitNumberADC1);

      for(int ADC_int = 0; ADC_int < 2; ADC_int++){
	
	if(!ADC_Status[ADC_int + i*NumOfADC]) continue;
	
	if(ADC_int == 0){
	  
	  for(int chan = 0; chan < HitNumberADC0; chan++){
	    
	    EVENT[iev++] = v550[i]->GetEvent(ADC_int);

	  }//chan
	  
	}//ADC0
	
	if(ADC_int == 1){
	  
	  for(int chan = 0; chan < HitNumberADC1; chan++){
	    
	    EVENT[iev++] = v550[i]->GetEvent(ADC_int);
   
	  }//chan
	  
	}//ADC1

	EVENT[iev++] = ((0xAABBCC00 | i << 1) | ADC_int); /*-- end of ADC --*/

      }//ADC_int

    }//i
      
    EVENT[iev] = 0xAABBCCDD; /*-- end of event --*/
    fwrite(EVENT,4,iev + 1,fp);

  }//taking data
  
  fclose(fp);

  return 1;

}//Run

int RunDisplay(int RunNumber){

  v551->Init(NumOfChan);
  for(int i = 0; i < NumOfADC; i++) v550[i]->Init(NumOfChan);

  //Display variables
  FILE* displayFile = NULL; 
  int displayPointer = 0;

  char OFName[200];

  //Removing old display files
  sprintf(OFName,"./Display/display%d.dat",displayPointer);
  while(remove(OFName)==0){
    displayPointer++;
    sprintf(OFName,"./Display/display%d.dat",displayPointer);
  }

  displayPointer = 0;

  sprintf(OFName,"./DATA/si_run%d.dat",RunNumber);

  FILE* fp = fopen(OFName,"r");

  if(fp){

    printf("Do you want to rewrite file %s (y/n) \n\r",OFName);

    fgets(CharTmp,20,stdin);
    CharTmp[0] = toupper(CharTmp[0]);

    switch(CharTmp[0]){
      
    case 'Y':
      fclose(fp);
      fp = fopen(OFName,"w");
      break;
      
    case 'N':
      return 1;
      
    default:
      break; 
  
    }//switch
    
  }//if
  else{
    fp = fopen(OFName,"w");
    if(fp == NULL){
      printf("!!! Warning: Can not open file %s \n",OFName);
      return 1;
    }
  }

  /*---  Run note  ---*/
  printf("Note:");  
  fgets(OFName,200,stdin);
 
  unsigned int HitNumberADC0;
  unsigned int HitNumberADC1;

  unsigned int EVENT[BuffSize + 8];
  unsigned int ievent = 0;
  int iev;

  //event time 
  struct timeval tv;
  unsigned int sec;
  unsigned int microsec;
  time_t    timer;
  struct tm *date;

 /*---  write header  ---*/

  time(&timer);
  date = localtime(&timer);
  fprintf(fp,"*FORM = 04 marker=0xAABBCCDD\n");
  fprintf(fp,"*RUN = %d time %d:%d, date %d/%d/%d \n",RunNumber,date->tm_hour,date->tm_min,date->tm_mday,date->tm_mon+1,date->tm_year+1900);
  fprintf(fp,"*Calibration = %d, ",FLAG_CALIB);
  for(int im = 0; im < NumOfADC; im++){
    for(int ic = 0; ic < 2; ic++){ 
      fprintf(fp,"ADC %d = %d, ",ic + im*NumOfADC,ADC_Status[ic + im*NumOfADC]);
    }
  }
  fprintf(fp,"\n");
  
  fprintf(fp,"*init_SEQ: t1=%d, t2=%d, t3=%d, t4=%d, t5=%d \n",v551->time1,v551->time1,v551->time3,v551->time4,v551->time5);
  fprintf(fp,"*REM = %s",OFName);

  //taking data
  while(sig_int){
    
    if(!(ievent%10)){

      if(displayFile) fclose(displayFile);
      sprintf(OFName,"./Display/display%d.dat",displayPointer);
      displayFile = fopen(OFName,"w");
      displayPointer++;

    }

    while(!v551->GetBusy()) if(!sig_int) break;

    iev = 0;
    gettimeofday(&tv,NULL);
    sec = tv.tv_sec;
    microsec = tv.tv_usec;
    EVENT[iev++] = ievent;
    EVENT[iev++] = sec;
    EVENT[iev++] = microsec;
    EVENT[iev++] = 0;

    //waiting for data ready 
    while(!v551->GetDataRedy()) if(!sig_int) break;
 
    ievent++;
    
    printf("Event = %d \n\r",ievent);

    for(int i = 0; i < NumOfADC; i++){
      
      v550[i]->GetWordCounter(HitNumberADC0,HitNumberADC1);

      for(int ADC_int = 0; ADC_int < 2; ADC_int++){
	
	if(!ADC_Status[ADC_int + i*NumOfADC]) continue;
	
	if(ADC_int == 0){
	  
	  for(int chan = 0; chan < HitNumberADC0; chan++){
	    
	    EVENT[iev++] = v550[i]->GetEvent(ADC_int);

	  }//chan
	  
	}//ADC0
	
	if(ADC_int == 1){
	  
	  for(int chan = 0; chan < HitNumberADC1; chan++){
	    
	    EVENT[iev++] = v550[i]->GetEvent(ADC_int);
   
	  }//chan
	  
	}//ADC1
	
	EVENT[iev++] = ((0xAABBCC00 | i << 1) | ADC_int); /*-- end of ADC --*/
	
      }//ADC_int
      
    }//i
      
    EVENT[iev] = 0xAABBCCDD; /*-- end of event --*/
    fwrite(EVENT,4,iev + 1,fp);
    if(displayFile) fwrite(EVENT,4,iev + 1,displayFile);

  }//taking data
  
  fclose(fp);
  if(displayFile) fclose(displayFile);

  return 1;

}//RunDisplay

void CalibAutoTrig(){

  unsigned int HitNumberADC0;
  unsigned int HitNumberADC1;
  unsigned int OR;
  unsigned int V;
  int ChNum;
  int ChData;
  int SilcPointer;

  v551->Init(NumOfChan);

  for(int i = 0; i < NumOfADC; i++){
    v550[i]->Init(NumOfChan);
    v550[i]->SetPedThrZero();
  }//i
  
  int* Ped = new int[BuffSize];
  int* Ped2 = new int[BuffSize];
  int* Noi = new int[BuffSize];
  int* Norm = new int[BuffSize];

  for(int tmp = 0; tmp < BuffSize; tmp++){
    
    Ped[tmp] = 0;
    Ped2[tmp] = 0;
    Noi[tmp] = 0;
    Norm[tmp] = 0;
  
  }//tmp

  for(int i_trig = 0; i_trig < 1000; i_trig++){

    v551->SoftwareTrigger();

    if((i_trig%100) == 0) printf("Calibration: Event - %d \n\r",i_trig);

    SilcPointer = 0;

    for(int i = 0; i < NumOfADC; i++){

      while(!v551->GetDataRedy());

      v550[i]->GetWordCounter(HitNumberADC0,HitNumberADC1);

       for(int ADC_int = 0; ADC_int < 2; ADC_int++){
	
	if(!ADC_Status[ADC_int + i*NumOfADC]) continue;

	if(ADC_int == 0){

	  for(int chan = 0; chan < HitNumberADC0; chan++){
	    
	    v550[i]->GetFifo0(OR,V,&ChNum,&ChData);
	    
	    Ped[ChNum + SilcPointer*NumOfChan] += ChData;
	    Ped2[ChNum + SilcPointer*NumOfChan] += ChData*ChData;
	    Norm[ChNum + SilcPointer*NumOfChan] += 1;	    
	    
	  }//chan
	  SilcPointer++;
	  
	}//ADC0
	
	if(ADC_int == 1){
	  
	  for(int chan = 0; chan < HitNumberADC1; chan++){
	    
	    v550[i]->GetFifo1(OR,V,&ChNum,&ChData);
	    Ped[ChNum + SilcPointer*NumOfChan] += ChData;
	    Ped2[ChNum + SilcPointer*NumOfChan] += ChData*ChData;
	    Norm[ChNum + SilcPointer*NumOfChan] += 1;	    

	  }//chan
	  SilcPointer++;
	  
	}//ADC1
	
      }//ADC_int
      
    }//i

  }//i_trig

  for(int tmp = 0; tmp < BuffSize; tmp++){
  
    if(Norm[tmp] > 1){
      Ped[tmp] = Ped[tmp]/Norm[tmp];
      Ped2[tmp] = Ped2[tmp]/Norm[tmp];
      Noi[tmp] = (int)(sqrt((Norm[tmp]/(Norm[tmp] - 1))*(Ped2[tmp] - Ped[tmp]*Ped[tmp])));
    }
    else{
      Ped[tmp] = 0;
      Noi[tmp] = 0;
    }

  }//tmp
  
  int ped_tmp, thr_tmp;

  SilcPointer = 0;

  for(int i = 0; i < NumOfADC; i++){
    for(int ADC_int = 0; ADC_int < 2; ADC_int++){
      
      if(!ADC_Status[ADC_int + i*NumOfADC]) continue;
      
      for(int chan = 0; chan < NumOfChan; chan++){

	ped_tmp = Ped[chan + SilcPointer*NumOfChan];
	thr_tmp = ped_tmp + 1*Noi[chan + SilcPointer*NumOfChan];

	v550[i]->SetPedestalThreshold(ADC_int,chan,ped_tmp,thr_tmp);

      }//chan
      SilcPointer++;
      
    }//ADC_int
  }//i
  
  ped_tmp = 0;
  thr_tmp = 0;

  int PedMax = 700;
  int NoiMax = 100;

  unsigned int hPed[NumOfChan];
  unsigned int hThr[NumOfChan];
  unsigned int hPedestal[PedMax];
  unsigned int hNoise[NoiMax];

  SilcPointer = 0;

  for(int i = 0; i < NumOfADC; i++){
    for(int ADC_int = 0; ADC_int < 2; ADC_int++){
      
      mreset(hPed,NumOfChan);
      mreset(hThr,NumOfChan);
      mreset(hPedestal,PedMax);
      mreset(hNoise,NoiMax);
      
      if(!ADC_Status[ADC_int + i*NumOfADC]) continue;
      
      for(int chan = 0; chan < NumOfChan; chan++){
	v550[i]->GetPedestalThreshold(ADC_int,chan,&ped_tmp,&thr_tmp);
	mfill(hPed,NumOfChan,chan,ped_tmp);
	mfill(hThr,NumOfChan,chan,thr_tmp);
	mfill(hPedestal,PedMax,Ped[chan + SilcPointer*NumOfChan],1);
	mfill(hNoise,NoiMax,Noi[chan + SilcPointer*NumOfChan],1);
      }//chan
      SilcPointer++;

      printf("------------------------------------------------- PLANE %d -------------------------------------------------\n\r",SilcPointer);
      hprint(hPed,NumOfChan,"Pedestals vs chan ");
      hprint(hThr,NumOfChan,"Threshold vs chan ");
      hprint(hPedestal,PedMax,"Pedestals distribution ");
      hprint(hNoise,NoiMax,"Noise distribution ");
      printf("-------------------------------------------------------------------------------------------------------------\n\r");
      
    }//ADC_int
  }//i
  
  FLAG_CALIB = 2;

  delete [] Ped;
  delete [] Ped2;
  delete [] Noi;
  delete [] Norm;
  
}//CalibAutoTrig

void CalibExtTrig(){

  unsigned int HitNumberADC0;
  unsigned int HitNumberADC1;
  unsigned int OR;
  unsigned int V;
  int ChNum;
  int ChData;
  int SilcPointer;

  v551->Init(NumOfChan);

  for(int i = 0; i < NumOfADC; i++){
    v550[i]->Init(NumOfChan);
    v550[i]->SetPedThrZero();
  }//i
  
  int* Ped = new int[BuffSize];
  int* Ped2 = new int[BuffSize];
  int* Noi = new int[BuffSize];
  int* Norm = new int[BuffSize];

  for(int tmp = 0; tmp < BuffSize; tmp++){
    
    Ped[tmp] = 0;
    Ped2[tmp] = 0;
    Noi[tmp] = 0;
    Norm[tmp] = 0;
  
  }//tmp

  for(int i_trig = 0; i_trig < 1000; i_trig++){

    if((i_trig%100) == 0) printf("Calibration: Event - %d \n\r",i_trig);

    SilcPointer = 0;

    for(int i = 0; i < NumOfADC; i++){

      while(!v551->GetDataRedy());

      v550[i]->GetWordCounter(HitNumberADC0,HitNumberADC1);

      for(int ADC_int = 0; ADC_int < 2; ADC_int++){
	
	if(!ADC_Status[ADC_int + i*NumOfADC]) continue;

	if(ADC_int == 0){

	  for(int chan = 0; chan < HitNumberADC0; chan++){
	    
	    v550[i]->GetFifo0(OR,V,&ChNum,&ChData);

	    Ped[ChNum + SilcPointer*NumOfChan] += ChData;
	    Ped2[ChNum + SilcPointer*NumOfChan] += ChData*ChData;
	    Norm[ChNum + SilcPointer*NumOfChan] += 1;	    

	  }//chan
	  SilcPointer++;
	  
	}//ADC0
	
	if(ADC_int == 1){
	  
	  for(int chan = 0; chan < HitNumberADC1; chan++){
	    
	    v550[i]->GetFifo1(OR,V,&ChNum,&ChData);
	    Ped[ChNum + SilcPointer*NumOfChan] += ChData;
	    Ped2[ChNum + SilcPointer*NumOfChan] += ChData*ChData;
	    Norm[ChNum + SilcPointer*NumOfChan] += 1;	    

	  }//chan
	  SilcPointer++;
	  
	}//ADC1
	
      }//ADC_int
      
    }//i

  }//i_trig

  for(int tmp = 0; tmp < BuffSize; tmp++){
  
    if(Norm[tmp] > 1){
      Ped[tmp] = Ped[tmp]/Norm[tmp];
      Ped2[tmp] = Ped2[tmp]/Norm[tmp];
      Noi[tmp] = (int)(sqrt((Norm[tmp]/(Norm[tmp] - 1))*(Ped2[tmp] - Ped[tmp]*Ped[tmp])));
    }
    else{
      Ped[tmp] = 0;
      Noi[tmp] = 0;
    }

  }//tmp
  
  int ped_tmp, thr_tmp;

  SilcPointer = 0;

  for(int i = 0; i < NumOfADC; i++){
    for(int ADC_int = 0; ADC_int < 2; ADC_int++){
      
      if(!ADC_Status[ADC_int + i*NumOfADC]) continue;
      
      for(int chan = 0; chan < NumOfChan; chan++){
	
	ped_tmp = Ped[chan + SilcPointer*NumOfChan];
	thr_tmp = ped_tmp + 1*Noi[chan + SilcPointer*NumOfChan];

	v550[i]->SetPedestalThreshold(ADC_int,chan,ped_tmp,thr_tmp);

      }//chan
      SilcPointer++;
      
    }//ADC_int
  }//i
  
  ped_tmp = 0;
  thr_tmp = 0;

  int PedMax = 700;
  int NoiMax = 100;

  unsigned int hPed[NumOfChan];
  unsigned int hThr[NumOfChan];
  unsigned int hPedestal[PedMax];
  unsigned int hNoise[NoiMax];

  SilcPointer = 0;

  for(int i = 0; i < NumOfADC; i++){
    for(int ADC_int = 0; ADC_int < 2; ADC_int++){
      
      mreset(hPed,NumOfChan);
      mreset(hThr,NumOfChan);
      mreset(hPedestal,PedMax);
      mreset(hNoise,NoiMax);
      
      if(!ADC_Status[ADC_int + i*NumOfADC]) continue;
      
      for(int chan = 0; chan < NumOfChan; chan++){
	v550[i]->GetPedestalThreshold(ADC_int,chan,&ped_tmp,&thr_tmp);
	mfill(hPed,NumOfChan,chan,ped_tmp);
	mfill(hThr,NumOfChan,chan,thr_tmp);
	mfill(hPedestal,PedMax,Ped[chan + SilcPointer*NumOfChan],1);
	mfill(hNoise,NoiMax,Noi[chan + SilcPointer*NumOfChan],1);
      }//chan
      SilcPointer++;

      printf("------------------------------------------------- PLANE %d -------------------------------------------------\n\r",SilcPointer);
      hprint(hPed,NumOfChan,"Pedestals vs chan ");
      hprint(hThr,NumOfChan,"Threshold vs chan ");
      hprint(hPedestal,PedMax,"Pedestals distribution ");
      hprint(hNoise,NoiMax,"Noise distribution ");
      printf("-------------------------------------------------------------------------------------------------------------\n\r");
      
    }//ADC_int
  }//i

  FLAG_CALIB = 1;
  
  delete [] Ped;
  delete [] Ped2;
  delete [] Noi;
  delete [] Norm;

}//CalibExtTrig

void SetZero(){

  for(int i = 0; i < NumOfADC; i++) v550[i]->SetPedThrZero();

  printf("============================================================================ \n\n\r");
  printf("!!! Warning: Right now all pedestals and thresholds are set to zero           \n\r");
  printf("!!! Warning: Before taking data you have to make calibration                  \n\r");
  printf("!!! Warning: Close the shutter and use calibration in the auto trigger mode \n\n\r");
  printf("============================================================================ \n\n\r");

  FLAG_CALIB = 1;

}//SetZero
